home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / pp / pp-6.0 / Format / rfc1148 / c-P2toRFC.c next >
Encoding:
C/C++ Source or Header  |  1991-12-18  |  15.8 KB  |  705 lines

  1. /* c-P2toRfc.c: rfc987(P2toRFC) filter channel */
  2.  
  3. # ifndef lint
  4. static char Rcsid[] = "@(#)$Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $";
  5. # endif
  6.  
  7. /*
  8.  * $Header: /xtel/pp/pp-beta/Format/rfc1148/RCS/c-P2toRFC.c,v 6.0 1991/12/18 20:20:34 jpo Rel $
  9.  *
  10.  * $Log: c-P2toRFC.c,v $
  11.  * Revision 6.0  1991/12/18  20:20:34  jpo
  12.  * Release 6.0
  13.  *
  14.  */
  15.  
  16.  
  17.  
  18. #include "util.h"
  19. #include "retcode.h"
  20. #include "qmgr.h"
  21. #include "q.h"
  22. #include "prm.h"
  23. #include "chan.h"
  24. #include "ap.h"
  25. #include "dr.h"
  26. #include <isode/cmd_srch.h>
  27. #include <sys/stat.h>
  28. #include "sys.file.h"
  29. #include <isode/usr.dirent.h>
  30. #include "tb_bpt88.h"
  31.  
  32. extern char    *quedfldir;
  33. extern char     *chndfldir;
  34. extern char    *cont_p2, *hdr_p2_bp, *hdr_p22_bp, *hdr_822_bp, *hdr_ipn_bp;
  35. extern void    rd_end(), sys_init(), or_myinit(), err_abrt(), dsap_init();
  36. extern int    convertresult;
  37. extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */];
  38.  
  39. CHAN         *mychan;
  40. char        *this_msg = NULL, *this_chan = NULL;
  41.  
  42. static struct type_Qmgr_DeliveryStatus *process ();
  43. static int initialise ();
  44. static int filterMsg();
  45. static int doFilter();
  46. static int link_rest();
  47. static int security_check ();
  48. static void dirinit ();
  49. static ADDR *getnthrecip ();
  50. int err_fatal;
  51. int order_pref;
  52. extern int ap_outtype;
  53. extern char    *local_dit;
  54.  
  55. /*   */
  56. /* main routine */
  57.  
  58. main (argc, argv)
  59. int     argc;
  60. char    **argv;
  61. {
  62.     sys_init(argv[0]);
  63.     or_myinit();
  64.     quipu_syntaxes();
  65.     dsap_init((char ***) NULL, (int *) NULL);
  66.     local_dit = NULLCP; /* hack to get full DNs */
  67.  
  68.     dirinit ();
  69. #ifdef PP_DEBUG
  70.     if (argc>1 && (strcmp(argv[1],"debug") == 0))
  71.         debug_channel_control(argc,argv,initialise,process,NULLIFP);
  72.     else
  73. #endif
  74.         channel_control (argc, argv, initialise, process,NULLIFP);
  75. }
  76.  
  77. /*   */
  78. /* routine to move to correct place in file system */
  79.  
  80. static void dirinit ()
  81. {
  82.     if (chdir (quedfldir) < 0)
  83.         err_abrt (RP_LIO, " Unable to change directory to '%s'",
  84.               quedfldir);
  85. }
  86.  
  87. /*   */
  88. /* channel initialise routine */
  89.  
  90. static void do_ch_info_flags(info)
  91. char    *info;
  92. {
  93.     char    *info_copy, *margv[20];
  94.     int    margc, ix;
  95.  
  96.     if (info == NULLCP) return;
  97.  
  98.     info_copy = strdup(info);
  99.     if ((margc = sstr2arg(info_copy, 20, margv, " \t")) > 0) {
  100.         for (ix = 0; ix < margc; ix++) {
  101.             if (lexequ (margv[ix], "uk") == 0) {
  102.                 order_pref = CH_UK_PREF;
  103.                 ap_outtype |= AP_PARSE_BIG;
  104.             } else
  105.                 PP_LOG(LLOG_EXCEPTIONS,
  106.                        ("Unknown ch_info flag '%s'",
  107.                     margv[ix]));
  108.         }
  109.     }
  110.     free(info_copy);
  111. }
  112.  
  113. static int initialise (arg)
  114. struct type_Qmgr_Channel *arg;
  115. {
  116.     char *name = NULL;
  117.  
  118.     name = qb2str(arg);
  119.  
  120.     if ((mychan = ch_nm2struct(name)) == NULLCHAN) {
  121.         PP_OPER(NULLCP,
  122.                ("Chans/rfc987 : Channel '%s' not known",name));
  123.         if (name != NULL) free(name);
  124.         return NOTOK;
  125.     }
  126.     
  127.     order_pref = CH_USA_PREF;
  128.     ap_outtype = AP_PARSE_SAME;
  129.     if (mychan->ch_out_info != NULLCP) 
  130.         do_ch_info_flags(mychan->ch_out_info);
  131.  
  132.                 
  133.     /* check if a rfc987 channel */
  134.     if (name != NULL) free(name);
  135.  
  136.     ap_use_percent();
  137.     ap_norm_all_domains();
  138.  
  139.     return OK;
  140. }
  141.  
  142. /*   */
  143. /* routine to check if allowed to rfc987 filter this message */
  144. static int security_check (msg)
  145. struct type_Qmgr_ProcMsg *msg;
  146. {
  147.     char *msg_file = NULL, *msg_chan = NULL;
  148.     int result;
  149.  
  150.     result = TRUE;
  151.     msg_file = qb2str (msg->qid);
  152.     msg_chan = qb2str (msg->channel);
  153.  
  154.     if ((mychan == NULLCHAN) || (strcmp(msg_chan,mychan->ch_name) !=0)) {
  155.         PP_LOG(LLOG_EXCEPTIONS,
  156.                ("Chans/rfc987 channel err: '%s'",msg_chan));
  157.         result = FALSE;
  158.     }
  159.     if (msg_file != NULL) free(msg_file);
  160.     if (msg_chan != NULL) free(msg_chan);
  161.     return result;
  162. }
  163.  
  164. /*   */
  165. /* routine called to do rfc987 filter */
  166.  
  167. static struct type_Qmgr_DeliveryStatus *process (arg)
  168. struct type_Qmgr_ProcMsg *arg;
  169. {
  170.     struct prm_vars    prm;
  171.     Q_struct    que;
  172.     ADDR        *sender = NULL;
  173.     ADDR        *recips = NULL;
  174.     int         rcount, first_failureDR, retval;
  175.     struct type_Qmgr_UserList     *ix;
  176.     ADDR                *adr;
  177.     char        *error = NULLCP;
  178.  
  179.     bzero((char *) &que,sizeof(que));
  180.     first_failureDR = TRUE;
  181.     delivery_init(arg->users);
  182.     delivery_setall(int_Qmgr_status_messageFailure);
  183.     
  184.     if (security_check(arg) != TRUE)
  185.         return deliverystate;
  186.  
  187.     if (this_msg != NULL) free(this_msg);
  188.     if (this_chan != NULL) free(this_chan);
  189.  
  190.     this_msg = qb2str(arg->qid);
  191.     this_chan = qb2str(arg->channel);
  192.  
  193.     PP_LOG(LLOG_NOTICE,
  194.            ("Chans/rfc987 filtering msg '%s' through '%s'",this_msg, this_chan));
  195.  
  196.     if (rp_isbad(rd_msg(this_msg,&prm,&que,&sender,&recips,&rcount))) {
  197.         PP_LOG(LLOG_EXCEPTIONS,
  198.             ("Chans/rfc987 rd_msg err: '%s'",this_msg));
  199.         rd_end();
  200.         return delivery_setallstate (int_Qmgr_status_messageFailure,
  201.                          "Can't read message");
  202.     }
  203.  
  204.     /* check each recipient for processing */
  205.     for (ix = arg->users; ix; ix = ix->next) {
  206.         if ((adr = getnthrecip(&que,ix->RecipientId->parm)) == NULL) {
  207.             PP_LOG(LLOG_EXCEPTIONS,
  208.                 ("Chans/rfc987 : failed to find recipient %d of msg '%s'",ix->RecipientId->parm, this_msg));
  209.  
  210.              delivery_setstate(ix->RecipientId->parm,
  211.                       int_Qmgr_status_messageFailure,
  212.                       "Unable to find specified recipient");
  213.             continue;
  214.         }
  215.     
  216.         switch (chan_acheck(adr, mychan, 1, (char **)NULL)) {
  217.             case OK:
  218.             if (filterMsg(this_msg,adr,&que, &error) == NOTOK) {
  219.                 if (convertresult == NOTOK) {
  220.                     PP_LOG(LLOG_EXCEPTIONS,
  221.                            ("Chans/rfc1138 : completely failed to filter msg '%s' for recip '%d' on channel '%s'. Sending a DR",
  222.                         this_msg, adr->ad_no, this_chan));
  223.                     set_1dr(&que, adr->ad_no, this_msg,
  224.                         DRR_CONVERSION_NOT_PERFORMED,
  225.                         DRD_CONTENT_SYNTAX_ERROR,
  226.                         (error == NULLCP) ? "Unable to parse the p2 header" : error);
  227.                     delivery_set(adr->ad_no,
  228.                              (first_failureDR == TRUE) ? int_Qmgr_status_negativeDR : int_Qmgr_status_failureSharedDR);
  229.                     first_failureDR = FALSE;
  230.                 } else {
  231.                     PP_LOG(LLOG_EXCEPTIONS,
  232.                            ("Chans/rfc987 : failed to filter msg '%s' for recip '%d' on channel '%s'",this_msg, adr->ad_no, this_chan));
  233.                     delivery_setstate(adr->ad_no,
  234.                               int_Qmgr_status_messageFailure,
  235.                               (error == NULLCP) ? "Problems doing 1138 conversion" : error);
  236.                 }
  237.             } else {
  238.                 /* CHANGE update adr->ad_rcnt in struct and in file */
  239.                 adr->ad_rcnt++;
  240.                 wr_ad_rcntno(adr,adr->ad_rcnt);
  241.                 delivery_set(adr->ad_no,
  242.                          int_Qmgr_status_success);
  243.             }
  244.             break;
  245.             default:
  246.             break;
  247.         }
  248.         if (error != NULLCP) {
  249.             free(error);
  250.             error = NULLCP;
  251.         }
  252.     }
  253.     if (rp_isbad(retval = wr_q2dr(&que, this_msg))) {
  254.         PP_LOG(LLOG_EXCEPTIONS,
  255.                ("%s wr_q2dr failure '%d'",mychan->ch_name,retval));
  256.         delivery_resetDRs(int_Qmgr_status_messageFailure);
  257.     }
  258.     rd_end();
  259.     q_free (&que);
  260.     prm_free(&prm);
  261.     return deliverystate;
  262. }
  263.  
  264. /*   */
  265. static int filterMsg (msg,recip,qp, ep)
  266. /* return OK if managed to filter msg through mychan for recip */
  267. char        *msg;
  268. ADDR        *recip;
  269. Q_struct    *qp;
  270. char        **ep;
  271. {
  272.     char    *origdir = NULL,
  273.             *newdir = NULL;
  274.     int    result = OK;
  275.     struct stat statbuf;
  276.  
  277.     if (qid2dir(msg, recip, TRUE, &origdir) != OK) {
  278.         PP_LOG(LLOG_EXCEPTIONS,
  279.                ("Chans/rfc987 original directory not found for recipient %d of message '%s'",recip->ad_no, msg));
  280.         *ep = strdup("source directory not found");
  281.         result = NOTOK;
  282.     }
  283.  
  284.     /* temporary change to get new directory name */
  285.     recip->ad_rcnt++;
  286.     if ((result == OK) 
  287.         && (qid2dir(msg, recip, FALSE, &newdir) != OK)) {
  288.         PP_LOG(LLOG_EXCEPTIONS,
  289.                ("Chans/rfc987 couldn't construct new directory for recipient '%d' of message '%s'",recip->ad_no, msg));
  290.         *ep = strdup("Unable to construct destination directory");
  291.         result = NOTOK;
  292.     }
  293.     recip->ad_rcnt--;
  294.     
  295.     if ((result == OK)
  296.         && (stat(newdir, &statbuf) == OK)
  297.         && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
  298.         /* directory already exists and so filter already done */
  299.  
  300.         if (origdir != NULL) free(origdir);
  301.         if (newdir != NULL) free(newdir);
  302.         return OK;
  303.     }
  304.  
  305.     if ((result == OK) && (doFilter(origdir,newdir,msg, 
  306.                     qp, ep)!= OK))
  307.  
  308.         result = NOTOK;
  309.  
  310.     if (origdir != NULL) free(origdir);
  311.     if (newdir != NULL) free(newdir);
  312.     return result;
  313. }
  314.  
  315. /*   */
  316. char    olddir[MAXPATHLENGTH],
  317.     newdir[MAXPATHLENGTH],
  318.     xtra_822hdrs[MAXPATHLENGTH];
  319.  
  320. int    *dir_flags = NULL,
  321.     num_dir_flags = 0,
  322.     dirlevel = 0;
  323.  
  324. #define    INC    5
  325.  
  326. static void resize_dir_flags()
  327. {
  328.     num_dir_flags += INC;
  329.     if (dir_flags == NULL)
  330.         dir_flags = (int *) calloc((unsigned int)num_dir_flags, sizeof(int));
  331.     else
  332.         dir_flags = (int *) realloc( (char *) dir_flags, 
  333.                         (unsigned) (num_dir_flags * sizeof(int)));
  334. }
  335.  
  336. static int    is822hdrfile(file)
  337. char        *file;
  338. {
  339.     char    buf[LINESIZE];
  340.     FILE    *fp;
  341.  
  342.     (void) sprintf(xtra_822hdrs, "%s/%s", olddir, file);
  343.     if ((fp = fopen(xtra_822hdrs,"r")) == NULL)
  344.     {
  345.         PP_SLOG(LLOG_EXCEPTIONS, xtra_822hdrs,
  346.             ("Can't open file"));
  347.         return FALSE;
  348.     }
  349.  
  350.     if (fgets (buf, LINESIZE - 1, fp) == NULL)
  351.     {
  352.         PP_DBG (("Null file '%s'",xtra_822hdrs));
  353.         fclose(fp);
  354.         return FALSE;
  355.     }
  356.  
  357.     buf [strlen(buf) - 1] = '\0'; /* remove \n */
  358.     if (lexnequ (buf, "RFC-822-HEADERS:",
  359.              strlen("RFC-822-HEADERS:")) != 0
  360.         && lexnequ (buf, "Comments:",
  361.             strlen("Comments:")) != 0)
  362.     {
  363.         fclose (fp);
  364.         return FALSE;
  365.     }
  366.  
  367.     fclose(fp);
  368.     return TRUE;
  369. }
  370.  
  371.  
  372. static int    is_xtra_822hdrs(entry)
  373. struct dirent    *entry;
  374. {
  375.     if ((strncmp(entry->d_name,"1.",2) == 0)
  376.         && (is822hdrfile(entry->d_name) == TRUE)) {
  377.         (void) sprintf(xtra_822hdrs, "%s/%s", olddir, entry->d_name);
  378.         return 1;
  379.     }
  380.     return 0;
  381. }
  382.  
  383. static    char    *get_xtra_822hdrs(dir)
  384. char    *dir;
  385. {
  386.     int    num;
  387.     struct dirent    **namelist;
  388.  
  389.     num = _scandir(dir, &namelist, is_xtra_822hdrs, NULL);
  390.     if (num == 0) {
  391.         dir_flags[dirlevel] = FALSE;
  392.         return NULLCP;
  393.     } else {
  394.         dir_flags[dirlevel] = TRUE;
  395.         return xtra_822hdrs;
  396.     }
  397. }
  398.  
  399. extern char    *ia5_bp;
  400.  
  401. static doFilter (orig, new, msg, qp, ep)
  402. /* filters orig directory through mychan to new directory */
  403. char        *orig,
  404.         *new,
  405.         *msg;
  406. Q_struct    *qp;
  407. char        **ep;
  408. {
  409.     char        hdrp2[MAXPATHLENGTH],
  410.             hdr822[MAXPATHLENGTH], *ipn_body;
  411.     int        result = OK;
  412.     struct stat     statbuf;
  413.     char        buf[BUFSIZ];
  414.     (void) sprintf(newdir, "%s/tmp.%s", 
  415.                msg, mychan->ch_name);
  416.     
  417.     if (stat(newdir, &statbuf) == OK) {
  418.         char    *cmd_line;
  419.         /* exists so remove it */
  420.         cmd_line = malloc((unsigned) (strlen("rm -rf ") +
  421.                            strlen(newdir) + 1));
  422.         sprintf(cmd_line, "rm -rf %s", newdir);
  423.         system(cmd_line);
  424.         if (cmd_line != NULL) free(cmd_line);
  425.     }
  426.  
  427.     if (mkdir(newdir, 0777) != OK) {
  428.         PP_SLOG(LLOG_EXCEPTIONS, newdir,
  429.             ("Can't make directory"));
  430.         (void) sprintf(buf,
  431.                    "Failed to make temp directory '%s'",
  432.                    newdir);
  433.         *ep = strdup(buf);
  434.         result = NOTOK;
  435.     }
  436.  
  437.     if (result == OK) {
  438.         /* filter from orig to newdir */
  439.         /* find p2 header to filter */
  440.         LIST_BPT    *ix = mychan -> ch_hdr_in;
  441.         int    found = FALSE;
  442.         ipn_body = NULLCP;
  443.         
  444.         while (found == FALSE
  445.                && ix != NULLIST_BPT) {
  446.             sprintf(hdrp2,"%s/%s",orig, ix -> li_name);
  447.             if (stat(hdrp2, &statbuf) == OK)
  448.                 found = TRUE;
  449.             else 
  450.                 ix = ix -> li_next;
  451.         }
  452.  
  453.         if (found == FALSE) {
  454.             PP_OPER(NULLCP,
  455.                 ("Format/P2toRFC : cannot find p2 hdr"));
  456.             (void) sprintf (buf,
  457.                     "Cannot find p2 hdr");
  458.             *ep = strdup(buf);
  459.             return NOTOK;
  460.         }
  461.  
  462.         sprintf(hdr822, "%s/1.%s", newdir, ia5_bp);
  463.         ipn_body = strdup(hdr822);
  464.         
  465.         sprintf(hdr822,"%s/%s",newdir,hdr_822_bp);
  466.         sprintf(olddir,"%s",orig);
  467.         dirlevel = 0;
  468.         resize_dir_flags();
  469.  
  470.         result = P2toRFC(hdrp2,get_xtra_822hdrs(orig),qp,NULLCP,
  471.                  hdr822,ipn_body,ep);
  472.  
  473.         if (ipn_body) free(ipn_body);
  474.         if (result != NOTOK) {
  475.             err_fatal = FALSE;
  476.             link_rest(orig, ep);
  477.             if (err_fatal == TRUE)
  478.                 result = NOTOK;
  479.         }
  480.         /* if success rename newdir to new */
  481.  
  482.         if ((result == OK) && (rename(newdir,new) == -1)) {
  483.             PP_SLOG(LLOG_EXCEPTIONS, "rename",
  484.                 ("Can't rename directory '%s' to '%s'",
  485.                  newdir, new));
  486.             (void) sprintf (buf,
  487.                     "Unable to rename temp dir from '%s' to '%s'",
  488.                     newdir, new);
  489.             *ep = strdup(buf);
  490.             result = NOTOK;
  491.         }
  492.     }
  493.     return result;
  494. }
  495.  
  496. /*   */
  497. /* link rest across from orig to newdir */
  498. /* may have to do some renumbering if 1.ia5 is extra headers */
  499.  
  500. /* origdir and newdir are set to current dirlevel of directories */
  501. char    *linkerror = NULLCP;
  502.  
  503. static int    do_link(entry)
  504. struct dirent    *entry;
  505. {
  506.     struct    stat statbuf;
  507.     struct dirent    **namelist;
  508.     int        num;
  509.     char        oldfullname[MAXPATHLENGTH],
  510.             newfullname[MAXPATHLENGTH],
  511.             buf[BUFSIZ],
  512.             *ix;
  513.  
  514.     if ((strcmp(entry->d_name,".") == 0)
  515.         || (strcmp(entry->d_name,"..") == 0))
  516.         return 0;
  517.  
  518.     if ((dir_flags[dirlevel] == TRUE)
  519.         && (strncmp(entry->d_name,"1.",2) == 0))
  520.         /* already done so ignore */
  521.         return 0;
  522.  
  523.     if (strcmp(entry->d_name, hdr_p2_bp) == 0
  524.         || strcmp(entry->d_name, hdr_p22_bp) == 0
  525.         || strcmp(entry->d_name, hdr_ipn_bp) == 0
  526.         || strcmp (entry->d_name, 
  527.                rcmd_srch (BPT_P2_DLIV_TXT, 
  528.                   bptbl_body_parts88)) == 0)
  529.         /* already dealt with */
  530.         return 0;
  531.  
  532.     (void) sprintf(oldfullname, "%s/%s",olddir,entry->d_name);
  533.  
  534.     /* create new filename */
  535.  
  536.     if (isdigit(*(entry->d_name))
  537.         && (dir_flags[dirlevel] == TRUE)) {
  538.         /* need to alter number (decrement) */
  539.         ix = index(entry->d_name,'.');
  540.         *ix = '\0';
  541.         num = atoi(entry->d_name);
  542.         *ix = '.';
  543.         sprintf(newfullname,"%s/%d%s",newdir,--num,ix);
  544.     } else
  545.         /* just copy */
  546.         sprintf(newfullname,"%s/%s",newdir,entry->d_name);
  547.     
  548.             
  549.     if ((stat(oldfullname,&statbuf) == OK)
  550.         && ((statbuf.st_mode & S_IFMT) == S_IFDIR)) {
  551.         /* directory so do scandir on it */
  552.         char        hdrp2[MAXPATHLENGTH],
  553.                 hdr822[MAXPATHLENGTH],
  554.                 delivery_info[MAXPATHLENGTH],
  555.                 *del_info;
  556.         struct stat     statbuf;
  557.         int        found;
  558.         LIST_BPT    *bix = mychan -> ch_hdr_in;
  559.         
  560.         if (mkdir(newfullname, 0777) != OK) {
  561.             PP_SLOG(LLOG_EXCEPTIONS, newfullname,
  562.                 ("Can't make directory"));
  563.             exit(-1);
  564.         }
  565.         dirlevel++;
  566.         if (dirlevel >= num_dir_flags)
  567.             resize_dir_flags();
  568.  
  569.         sprintf(olddir, "%s", oldfullname);
  570.         sprintf(newdir, "%s", newfullname);
  571.  
  572.         found = FALSE;
  573.         /* deal with p2 hdr in this directory if there */
  574.         while (found == FALSE
  575.                && bix != NULLIST_BPT) {
  576.             sprintf(hdrp2,"%s/%s",olddir, bix -> li_name);
  577.             if (stat(hdrp2, &statbuf) == OK)
  578.                 found = TRUE;
  579.             else
  580.                 bix = bix -> li_next;
  581.         }
  582.         
  583.         if (found == FALSE) {
  584.             PP_OPER(NULLCP,
  585.                    ("Format/P2toRFC : cannot find p2 hdr in forwarded msg"));
  586.             linkerror = strdup("cannot find p2 hdr in forwarded msg");
  587.             return 0;
  588.         }
  589.  
  590.         sprintf(hdr822,"%s/%s",
  591.             newdir, hdr_822_bp);
  592.         sprintf(delivery_info, "%s/%s",
  593.             olddir, 
  594.             rcmd_srch (BPT_P2_DLIV_TXT,
  595.                    bptbl_body_parts88));
  596.         if (stat(delivery_info, &statbuf) == OK)
  597.             del_info = delivery_info;
  598.         else
  599.             del_info = NULLCP;
  600.  
  601.         if (P2toRFC(hdrp2,get_xtra_822hdrs(olddir),
  602.                 (Q_struct *) NULL, del_info,
  603.                 hdr822, NULLCP, 
  604.                 &linkerror) != OK) {
  605.             err_fatal = TRUE;
  606.             return 0;
  607.         }
  608.  
  609.         num = _scandir(olddir,&namelist, do_link, NULL);
  610.         /* rewind newdir and olddir */
  611.         ix = rindex(olddir,'/');
  612.         *ix = '\0';
  613.         ix = rindex(newdir,'/');
  614.         *ix = '\0';
  615.         dirlevel--;
  616.  
  617.     } else
  618.         /* just link */
  619.         if (link(oldfullname, newfullname) == -1) {
  620.             PP_SLOG(LLOG_EXCEPTIONS, "link",
  621.                    ("Can't link from '%s' to '%s'",oldfullname,newfullname));
  622.             exit(-1);
  623.         }
  624.     return 0;
  625. }
  626.     
  627.  
  628. static int link_rest(orig, ep)
  629. char    *orig;
  630. char    **ep;
  631. {
  632.     int num;
  633.     struct dirent    **namelist;
  634.  
  635.     num = _scandir(orig,&namelist, do_link, NULL);
  636.     if (linkerror != NULLCP) {
  637.         if (*ep == NULLCP) 
  638.             *ep = linkerror;
  639.         else
  640.             free(linkerror);
  641.         linkerror = NULLCP;
  642.     }
  643. }
  644.  
  645. /*   */
  646. /* auxilary routines to extr<act from lists */
  647. static ADDR *getnthrecip(que, num)
  648. Q_struct    *que;
  649. int        num;
  650. {
  651.     ADDR *ix = que->Raddress;
  652.  
  653.     if (num == 0)
  654.         return que->Oaddress;
  655.     while ((ix != NULL) && (ix->ad_no !=  num))
  656.         ix = ix->ad_next;
  657.     return ix;
  658. }
  659.  
  660. void    advise (what, fmt, a, b, c, d, e, f, g, h, i, j)
  661. char   *what,
  662.        *fmt,
  663.        *a,
  664.        *b,
  665.        *c,
  666.        *d,
  667.        *e,
  668.        *f,
  669.        *g,
  670.        *h,
  671.        *i,
  672.        *j;
  673. {
  674.     (void) fflush (stdout);
  675.  
  676.     fprintf (stderr, "RFCtoP2 test");
  677.     fprintf (stderr, fmt, a, b, c, d, e, f, g, h, i, j);
  678.     if (what)
  679.     (void) fputc (' ', stderr), perror (what);
  680.     else
  681.     (void) fputc ('\n', stderr);
  682.  
  683.     (void) fflush (stderr);
  684. }
  685.  
  686.  
  687. /* VARARGS 2 */
  688. void    adios (what, fmt, a, b, c, d, e, f, g, h, i, j)
  689. char   *what,
  690.        *fmt,
  691.        *a,
  692.        *b,
  693.        *c,
  694.        *d,
  695.        *e,
  696.        *f,
  697.        *g,
  698.        *h,
  699.        *i,
  700.        *j;
  701. {
  702.     advise (what, fmt, a, b, c, d, e, f, g, h, i, j);
  703.     _exit (1);
  704. }
  705.